﻿using System;
using System.IO;
using System.Net.Mail;
using System.Globalization;
using System.Web.Mvc;
using WeBlog.Helpers;
using WeBlog.Interfaces;
using WeBlog.Models;

namespace WeBlog.Services {
	public class EmailService : IEmailService
	{
		private readonly DirectoryInfo _rootDirectory;	    
		private readonly SiteConfiguration _configuration;

		public EmailService(IUnitOfWork unitOfWork )
		{
			_configuration = SiteManager.CurrentConfiguration;
			_rootDirectory = FileManager.EmailDirectory;
		}

		private DirectoryInfo GetLocalizedDirectory()
		{
			DirectoryInfo info = _rootDirectory;

			if (CultureInfo.CurrentCulture != CultureInfo.GetCultureInfo("en-US"))
			{
				string path = Path.Combine(_rootDirectory.FullName, CultureInfo.CurrentCulture.Name);
				if (Directory.Exists(path))
					info = new DirectoryInfo(path);
			}
							
			return info;
		}

		private MailMessageTemplate GetMailTemplate(string name) {
			var file = new FileInfo(Path.Combine(GetLocalizedDirectory().FullName, name + ".txt"));

			if (!file.Exists)
				throw new FileNotFoundException("The mail template could not be found.", file.FullName );

			var template = new MailMessageTemplate(file);
			template.AssignVariable("SiteUrl", SiteManager.GetBaseUrl());
			template.AssignVariable("SiteName", _configuration.Name);
			return template;
		}
	
		//Email sent to user when they register
		public void SendRegistrationMail( User user )
		{
			var template = GetMailTemplate(MailMessageTemplate.Registered);
			var activationUri = UrlHelpers.GetPermalink(String.Format("Account/Activate/{0}", user.UserId )); 
			template.AssignVariable("ActivationUrl", activationUri.ToString() );
			MailMessage message = template.Execute();
			message.To.Add(new MailAddress(user.Email));
			message.From = new MailAddress(_configuration.NoReplyEmailAddress);
			SendEmail(message);
		}

		//Email sent to a user when they forgot their username
		public void SendForgotUsernameMail(User user)
		{
			var template = GetMailTemplate(MailMessageTemplate.ForgotUsername);       
			template.AssignVariable("UserName", user.Email);
			

			MailMessage message = template.Execute();
			message.To.Add(new MailAddress(user.Email));
			message.From = new MailAddress(_configuration.NoReplyEmailAddress);
			SendEmail(message);
		}

		//Email sent to user when thier account is reset
		public void SendResetPasswordMail(User user, string password )
		{
			var template = GetMailTemplate(MailMessageTemplate.PasswordReset);
			template.AssignVariable("UserName", user.Email);
			template.AssignVariable("Password", password);
			MailMessage message = template.Execute();
			message.To.Add(new MailAddress(user.Email));
			message.From = new MailAddress(_configuration.NoReplyEmailAddress);
			SendEmail(message);
		}

		//Email sent to user when their account is activated
		public void SendAccountActivatedMail(User user )
		{
			var template = GetMailTemplate(MailMessageTemplate.AccountActivation);         
			MailMessage message = template.Execute();
			message.To.Add(new MailAddress(user.Email));
			message.From = new MailAddress(_configuration.NoReplyEmailAddress);
			SendEmail(message);
		}

		//Email sent to user when a account is created on their behalf by an admin
		public void SendAccountNotificationEmail(User user, string password )
		{
			var template = GetMailTemplate(MailMessageTemplate.NewAccountNotification);
			template.AssignVariable("Email", user.Email);
			template.AssignVariable("Password", password );
			MailMessage message = template.Execute();
			message.To.Add(new MailAddress(user.Email));
			message.From = new MailAddress(_configuration.NoReplyEmailAddress);
			SendEmail(message);
		}

		//Email sent from the contact page.
		public void SendContactMail(string email, string fullname, string subject, string text, MailAddressCollection recipients)
		{
			var template = GetMailTemplate(MailMessageTemplate.Contact);
			template.AssignVariable("Email", email);
			template.AssignVariable("FullName", fullname);
			template.AssignVariable("Message", text );
			var message = template.Execute();
			message.Subject = subject;
			foreach( var recipient in recipients )
			{
				message.To.Add( recipient );
			}            
			message.From = new MailAddress(email);            
			SendEmail(message);
		}

		//when a post is published an email should be sent to all the editors
		public void SendPostPublished(Post post, params string[] recipients)
		{
			var template = GetMailTemplate(MailMessageTemplate.PostPublished);
			template.AssignVariable("FullName", post.Author.FullName);
			template.AssignVariable("PostPermalink", post.GetPermalink().ToString());
			template.AssignVariable("PostTitle", post.Title);
			MailMessage message = template.Execute();
			message.From = new MailAddress(_configuration.NoReplyEmailAddress);
			message.To.Add(String.Join(",", recipients));   
			SendEmail(message);
		}

		//when a comment is flagged an email should be sent to all the editors who are subscribed
		public void SendCommentFlagged(PostComment comment, params string[] recipients )
		{
			var template = GetMailTemplate(MailMessageTemplate.CommentFlagged);
			template.AssignVariable("ContentUrl", comment.Post.GetPermalink().ToString());            
			MailMessage message = template.Execute();
			message.From = new MailAddress(_configuration.NoReplyEmailAddress);
			message.To.Add(String.Join(",", recipients));       
			SendEmail(message);
		}

		//when a post is flagged an email should be sent to all the editors who are subscribed
		public void SendPostFlagged(Post post, params string[] recipients)
		{
			var template = GetMailTemplate(MailMessageTemplate.PostFlagged);
			template.AssignVariable("PostTitle", post.Title);
			template.AssignVariable("PostPermalink", post.GetPermalink().ToString());         
			MailMessage message = template.Execute();
			message.From = new MailAddress(_configuration.NoReplyEmailAddress);
			message.To.Add( String.Join(",", recipients));       
			SendEmail(message);
		}

		public bool IsConfigured()
		{
			if (String.IsNullOrWhiteSpace(_configuration.SmtpServer))
				return false;

			return true;
		}

		public void SendEmail(MailMessage message)
		{
			if (IsConfigured() == false) return;

			var client = new SmtpClient( _configuration.SmtpServer, _configuration.SmtpPort ?? 25 )
			{
				EnableSsl = _configuration.SmtpEnableSsl ?? false,
				UseDefaultCredentials = true
			};

			if (!String.IsNullOrWhiteSpace(_configuration.SmtpUserName) && !String.IsNullOrWhiteSpace(_configuration.SmtpPassword))
			{
				client.Credentials = new System.Net.NetworkCredential(_configuration.SmtpUserName, _configuration.SmtpPassword);
				client.UseDefaultCredentials = false;
			}      
	 
			client.Send(message);
		}
	}
}